package srx.open.com.views;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import android.widget.TextView;

import srx.open.com.R;

/**
 * 下拉刷新，上拉加载 ListView
 *
 * @author taozhishan
 * @date 2015/3/29
 *
 */
public class RefreshListView extends ListView {

	private static final String TAG = "下拉刷新，上拉自动加载";
	private static final int DONE = 1;
	private final static int RELEASE_TO_REFRESH = 2;
	private final static int PULL_TO_REFRESH = 3;
	private final static int REFRESHING = 4;
	/** 下拉刷新头部 */
	private View mHeadView;
	/** 上拉加载尾部 */
	private View mFootView;
	private TextView mHeadTip;
	private ImageView mHeadProgress;
	private int mHeadViewHeight;
	private int mHeadViewWidth;
	private Animation animRotate;
	private int refreshState;
	private int firstItemIndex;
	private boolean loadEnable = true;
	private OnLoadListener onLoadListener;
	private boolean isLoading;
	private boolean isLoadFull;
	private int pageSize = 20;
	private OnRefreshListener refreshListener;
	private boolean isRecored = false;
	private int startY;
	private LessPaddingSetRunnable lessPaddingSetRunnable;
	private final static int RATIO = 3;
	private int lessDisPadding;
	private int moreDisPadding;
	private boolean isBack = false;
	private MorePaddingSetRunnable morePaddingSetRunnable;

	private RefreshHeaderController mRefreshHeaderController;

	public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context);
	}

	public RefreshListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public RefreshListView(Context context) {
		super(context);
		init(context);
	}

	/**
	 * 初始化 ListView
	 */
	@SuppressWarnings("ResourceType")
	private void init(Context mContext) {
		mRefreshHeaderController = new RefreshHeaderController();
		//
		mHeadView = View.inflate(mContext, R.layout.refresh_listview_header1,
				null);
		mFootView = View.inflate(mContext, R.layout.refresh_listview_footer,
				null);
		mHeadTip = (TextView) mHeadView.findViewById(R.id.tv_head_tip);
		mHeadProgress = (ImageView) mHeadView
				.findViewById(R.id.iv_head_rotation);

		mHeadKaTongProgress = (ImageView) mHeadView
				.findViewById(R.id.iv_head_caton_progress);
		measureView(mHeadView);
		mHeadViewHeight = mHeadView.getMeasuredHeight();
		mHeadViewWidth = mHeadView.getMeasuredWidth();
		// 设置headView的padding值,topPadding为其本身的负值,达到在屏幕中隐藏的效果
		mHeadView.setPadding(0, -mHeadViewHeight, 0, 0);
		mHeadView.invalidate();
		//
		mFootView.setPadding(0, -mHeadViewHeight, 0, 0);
		mFootView.invalidate();
		isLoadFull = true;
		//
		this.addHeaderView(mHeadView, null, false);
		this.addFooterView(mFootView, null, false);
		this.setOnScrollListener(onScrollListener);
		animRotate = AnimationUtils.loadAnimation(mContext,
				R.anim.rotate_progress);
		LinearInterpolator lir = new LinearInterpolator();
		animRotate.setInterpolator(lir);
		mHeadKaTongProgress.setBackgroundResource(R.anim.frame_loading);
		anim_katong = (AnimationDrawable) mHeadKaTongProgress.getBackground();
		refreshState = DONE;
	}

	OnRefreshScrollHeadListener mOnRefreshScrollHeadListener = null;

	public void setOnRefreshScrollHeadListener(OnRefreshScrollHeadListener onRefreshScrollHeadListener) {
		this.mOnRefreshScrollHeadListener = onRefreshScrollHeadListener;
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch (action) {
			case MotionEvent.ACTION_UP:
				if (isReachedBottom) {
					Log.d(TAG, "dispatchTouchEvent ACTION_UP:" + isReachedBottom);
				}
				break;
			case MotionEvent.ACTION_CANCEL:
				break;
			case MotionEvent.ACTION_DOWN:
				mRefreshHeaderController.onTouchDown(ev.getX(), ev.getY());
				break;
			case MotionEvent.ACTION_MOVE:
				if (isReachedBottom) {
					Log.d(TAG, "dispatchTouchEvent ACTION_MOVE:" + isReachedBottom);
				}
				//
				mRefreshHeaderController.onTouchMove(ev.getX(), ev.getY());
				float offsetY = mRefreshHeaderController.getOffsetY();
				boolean isMoveDown = (offsetY > 0);
				if (mOnRefreshScrollHeadListener != null)
					mOnRefreshScrollHeadListener.onScrollMove(this);
				if (isMoveDown) {
					if (mRefreshHeaderController.canScrollDownHead(this)) {
						// 回调隐藏外部的控件.
						if (mOnRefreshScrollHeadListener != null)
							mOnRefreshScrollHeadListener.onCanScrollDownHead(this);
						Log.d(TAG, "mRefreshHeaderController.canScrollDown(this) hide hide");
					} else {
						Log.d(TAG, "mRefreshHeaderController.canScrollDown(this)2222222222222:" + getFirstVisiblePosition());
					}
				} else {
					if (mRefreshHeaderController.canMoveUpHead(this)) {
						if (mOnRefreshScrollHeadListener != null)
							mOnRefreshScrollHeadListener.onCanScrollUpHead(this);
						// 回调显示外部的控件.
						Log.d(TAG, "!mRefreshHeaderController.canScrollUp(this) hide hide:" + getFirstVisiblePosition());
					} else {
						Log.d(TAG, "!mRefreshHeaderController.canScrollUp(this222222222222222222)" + getFirstVisiblePosition());
					}
				}
				break;
		}
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {

		switch (ev.getAction()) {
			// 当第一次触摸时
			case MotionEvent.ACTION_DOWN:

				if (firstItemIndex == 0) {
					isRecored = true;
					startY = (int) ev.getY();
					Log.e(TAG, startY + "");
				} else {
					Log.e(TAG, "首次触摸时firstItemIndex不为0,不执行下拉刷新");
				}

				break;

			// 手势移动时
			case MotionEvent.ACTION_CANCEL:
			case MotionEvent.ACTION_MOVE:
				int currentY = (int) ev.getY();

				//

				if (!isRecored && firstItemIndex == 0) {
					isRecored = true;
					Log.e(TAG, "从移动状态执行下拉刷新,开始记录..." + ",isRecored:" + isRecored);
					startY = currentY;
				}

				// 如果手指还没松手
				if (isRecored) {
					if (refreshState == DONE) {
						if (currentY - startY > 0) {
							refreshState = PULL_TO_REFRESH;
							changeHeadView();
						}
					}

					// 如果状态是 正在下拉刷新
					if (refreshState == PULL_TO_REFRESH) {
						setSelection(0);
						mHeadView.setPadding(0, (currentY - startY) / RATIO
								- mHeadViewHeight, 0, 0);
						rotateCycle(currentY - startY);

						lessDisPadding = (currentY - startY) / RATIO
								- mHeadViewHeight;
						if (lessDisPadding <= -mHeadViewHeight) {
							lessDisPadding = -mHeadViewHeight;
						}

						if ((currentY - startY) / RATIO >= mHeadViewHeight) {
							refreshState = RELEASE_TO_REFRESH;
							isBack = true;
							changeHeadView();
						} else if ((currentY - startY) <= 0) {
							// 上推到顶
							refreshState = DONE;
							changeHeadView();
						}
					}

					if (refreshState == RELEASE_TO_REFRESH) {
						setSelection(0);
						mHeadView.setPadding(0, (currentY - startY) / RATIO
								- mHeadViewHeight, 0, 0);
						rotateCycle(currentY - startY);

						lessDisPadding = (currentY - startY) / RATIO
								- mHeadViewHeight;
						if (lessDisPadding <= -mHeadViewHeight) {
							lessDisPadding = -mHeadViewHeight;
						}

						moreDisPadding = (currentY - startY) / RATIO
								- mHeadViewHeight;
						if (moreDisPadding <= 0) {
							moreDisPadding = 0;
						}

						if ((currentY - startY) / RATIO < mHeadViewHeight) {
							refreshState = PULL_TO_REFRESH;
							changeHeadView();
						}
					}

					if (refreshState == REFRESHING) {

						if (currentY - startY > 0) {
							mHeadView.setPadding(0, (currentY - startY) / RATIO, 0,
									0);

							lessDisPadding = (currentY - startY) / RATIO;
							if (lessDisPadding <= -mHeadViewHeight) {
								lessDisPadding = -mHeadViewHeight;
							}

							moreDisPadding = (currentY - startY) / RATIO;
							if (moreDisPadding <= 0) {
								moreDisPadding = 0;
							}
						}

					}

				}

				break;

			// 手指抬起时
			case MotionEvent.ACTION_UP:

				isRecored = false;
				if (refreshState == PULL_TO_REFRESH) {
					Log.e(TAG, "PULL_TO_REFRESH状态松手,回到原始状态");
					refreshState = DONE;
					changeHeadView();
				} else if (refreshState == RELEASE_TO_REFRESH) {
					Log.e(TAG, "RELEASE_TO_REFRESH状态松手,回到原始状态");
					refreshState = REFRESHING;
					changeHeadView();

					if (morePaddingSetRunnable != null) {
						morePaddingSetRunnable.stop();
					}
					morePaddingSetRunnable = new MorePaddingSetRunnable(
							moreDisPadding);
					post(morePaddingSetRunnable);

					onRefreshing();
				} else if (refreshState == REFRESHING) {

					if (firstItemIndex == 0) {

						if (morePaddingSetRunnable != null) {
							morePaddingSetRunnable.stop();
						}
						if (lessPaddingSetRunnable != null) {
							lessPaddingSetRunnable.stop();
						}
						morePaddingSetRunnable = new MorePaddingSetRunnable(
								moreDisPadding);
						post(morePaddingSetRunnable);
					} else {
						Log.e(TAG, "REFRESHING状态松手,保持该状态,headView被推出顶部");
					}

				}

				break;

			default:
				break;
		}

		return super.onTouchEvent(ev);
	}

	/** 下拉过程中旋转进度条 */
	private void rotateCycle(int del) {
		float angle = (float) (del);
		// 获取进度条图片属性
		ViewGroup.LayoutParams lp = mHeadProgress.getLayoutParams();
		mHeadProgress.setScaleType(ScaleType.MATRIX);
		Matrix matrix = new Matrix();
		// 绕(高度/2)和(宽度/2)的中心点进行旋转
		matrix.postRotate(angle, lp.width / 2f, lp.height / 2f);
		mHeadProgress.setImageMatrix(matrix);
	}

	boolean isReachedBottom = false;

	/**
	 * 滑动监听
	 */
	private OnScrollListener onScrollListener = new OnScrollListener() {

		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			isNeedLoad(view, scrollState);
		}

		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,
							 int visibleItemCount, int totalItemCount) {
			//
			isReachedBottom = ((firstVisibleItem + visibleItemCount) == totalItemCount);
			// 记录滚动时列表第一个完整可见的Position
			firstItemIndex = firstVisibleItem;
			if (mRefreshHeaderController.canMoveUpHead(RefreshListView.this)) {
				if (mOnRefreshScrollHeadListener != null)
					mOnRefreshScrollHeadListener.onCanScrollUpHead(RefreshListView.this);
			} else if (mRefreshHeaderController.canScrollDownHead(RefreshListView.this)) {
				if (mOnRefreshScrollHeadListener != null)
					mOnRefreshScrollHeadListener.onCanScrollDownHead(RefreshListView.this);
			}
			if (isReachedBottom) {
				Log.e(TAG, "滚动到最底部：" + isReachedBottom);
//				setMoreOnLoad();
			}
		}

	};
	private ImageView mHeadKaTongProgress;
	private AnimationDrawable anim_katong;

	/**
	 * 根据下拉的状态改变HeadView
	 */
	private void changeHeadView() {

		switch (refreshState) {

			case DONE:
				if (isRecored) {
					isRecored = false;
				} else {
					if (lessDisPadding >= 0) {
						lessDisPadding = 0;
					}
				}
				// 松开手回弹
				// 回退状态清除
				isBack = false;
				// 清除进度条旋转动画
				mHeadProgress.clearAnimation();
				if (anim_katong != null) {
					anim_katong.stop();
				}
				mHeadTip.setText("下拉刷新...");

				if (lessPaddingSetRunnable != null) {
					lessPaddingSetRunnable.stop();
				}
				if (morePaddingSetRunnable != null) {
					morePaddingSetRunnable.stop();
				}
				lessPaddingSetRunnable = new LessPaddingSetRunnable(lessDisPadding);
				post(lessPaddingSetRunnable);

				break;

			case PULL_TO_REFRESH:
				mHeadTip.setText("下拉刷新...");
				break;
			case RELEASE_TO_REFRESH:
				mHeadTip.setText("松开刷新...");
				break;
			case REFRESHING:
				// 开启进度条旋转动画
				mHeadProgress.startAnimation(animRotate);
				anim_katong.start();
				mHeadTip.setText("正在刷新...");
				break;
			default:
				break;
		}

	}

	/** 进入刷新的方法 */
	private void onRefreshing() {
		// 调用回调接口中的刷新方法
		if (refreshListener != null) {
			refreshListener.toRefresh();
		}
	}

	/**
	 * 注册一个用于刷新的回调接口
	 *
	 * @param refreshListener
	 */
	public void setOnRefreshListener(OnRefreshListener refreshListener) {
		// 获取传递过来的回调接口
		this.refreshListener = refreshListener;
	}

	/** 使用界面执行完刷新操作时调用此方法 */
	public void onRefreshComplete() {
		if (refreshState != DONE) {
			refreshState = DONE;
			changeHeadView();
		}
	}

	/**
	 * 使用界面传递给此ListView的回调接口,用于两者间通信
	 */
	public interface OnRefreshListener {
		public void toRefresh();
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	/**
	 * 每次上拉加载后，设置加载后数据的大小。
	 *
	 * @param resultSize
	 *            某一次加载后的大小
	 *
	 */
	public void setResultSize(int resultSize) {
		if (resultSize < pageSize) {
			isLoadFull = true;
			mFootView.setPadding(0, -mHeadViewHeight, 0, 0);
		} else {
			isLoadFull = false;
		}
	}

	/**
	 * 根据listview滑动的状态判断是否需要加载更多
	 *
	 * @param view
	 * @param scrollState
	 */
	private void isNeedLoad(AbsListView view, int scrollState) {
		if (!loadEnable) {
			return;
		}
		//
		try {
			// 当手指还在屏幕的时候.
			if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
					&& !isLoading
					&& view.getLastVisiblePosition() == view
					.getPositionForView(mFootView) && !isLoadFull) {
				setMoreOnLoad();
				Log.w(TAG, ">>>>>>SCROLL_STATE_TOUCH_SCROLL");
			} else if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
					&& !isLoading
					&& (view.getLastVisiblePosition() == view
					.getPositionForView(mFootView)) && !isLoadFull) {
				setSelection(getBottom());
				setMoreOnLoad();
				Log.w(TAG, ">>>>>>SCROLL_STATE_IDLE");
			}
		} catch (Exception e) {
		}
	}

	private void setMoreOnLoad() {
		isLoading = true;
		mFootView.setPadding(0, 0, 0, 0);
		onLoad();
	}

	/**
	 * 用于加载更多结束后的回调
	 */
	public void onLoadComplete() {
		isLoading = false;
		mFootView.setPadding(0, -mHeadViewHeight, 0, 0);
	}

	/**
	 * 进入加载的方法
	 */
	public void onLoad() {
		if (onLoadListener != null) {
			onLoadListener.onLoad();
		}
	}

	/**
	 * 定义加载更多接口
	 */
	public interface OnLoadListener {
		public void onLoad();
	}

	/**
	 * 设置加载监听
	 *
	 * @param onLoadListener
	 */
	public void setOnLoadListener(OnLoadListener onLoadListener) {
		this.onLoadListener = onLoadListener;
	}

	/**
	 * 预估头部的宽高。 创建时得不到头部的宽高, 所以需要进行测量获取宽高
	 */
	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	/**
	 * 头部回弹动画，采用分时间段设置Padding的方式
	 */
	private class LessPaddingSetRunnable implements Runnable {
		private Interpolator interpolator;
		private int disP;
		private long startTime = -1;
		private int currentPadding = -1;
		private boolean canRunning = true;

		public LessPaddingSetRunnable(int disPadding) {
			interpolator = new DecelerateInterpolator();
			this.disP = disPadding;
		}

		@Override
		public void run() {
			if (startTime == -1) {
				startTime = System.currentTimeMillis();
			} else {
				long normalizedTime = (1000 * (System.currentTimeMillis() - startTime)) / 200;
				normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);
				int deltaP = Math
						.round((disP + mHeadViewHeight)
								* interpolator
								.getInterpolation(normalizedTime / 1000f));
				currentPadding = disP - deltaP;
				mHeadView.setPadding(0, currentPadding, 0, 0);
			}

			if (canRunning && (currentPadding > -mHeadViewHeight)) {
				RefreshListView.this.postDelayed(this, 16);
			} else {
				stop();
			}
		}

		public void stop() {
			canRunning = false;
			removeCallbacks(this);
		}
	}

	/**
	 * 头部回弹动画，采用分时间段设置Padding的方式
	 */
	private class MorePaddingSetRunnable implements Runnable {
		private Interpolator interpolator;
		private int disP;
		private long startTime = -1;
		private int currentPadding = 1;
		private boolean canRunning = true;

		public MorePaddingSetRunnable(int disPadding) {
			interpolator = new DecelerateInterpolator();
			this.disP = disPadding;
		}

		@Override
		public void run() {
			if (startTime == -1) {
				startTime = System.currentTimeMillis();
			} else {
				long normalizedTime = (1000 * (System.currentTimeMillis() - startTime)) / 200;
				normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);
				int deltaP = Math
						.round((disP)
								* interpolator
								.getInterpolation(normalizedTime / 1000f));
				currentPadding = disP - deltaP;
				mHeadView.setPadding(0, currentPadding, 0, 0);
			}

			if (canRunning && (currentPadding > 0)) {
				RefreshListView.this.postDelayed(this, 16);
			} else {
				stop();
			}
		}

		public void stop() {
			canRunning = false;
			removeCallbacks(this);
		}
	}

}
